package com.aiwu.widget;

import android.app.Activity;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.customview.widget.ViewDragHelper;

import com.aiwu.PrefsHelper;
import com.aiwu.bean.ScreenConfig;
import com.aiwu.library.App;
import com.aiwu.pop.FastSettingDialog;
import com.aiwu.pop.SwitchScreenLayoutDialog;

import org.citra.citra_emu.NativeLibrary;
import org.citra.citra_emu.R;
import org.citra.citra_emu.features.settings.model.IntSetting;
import org.citra.citra_emu.features.settings.model.Setting;
import org.citra.citra_emu.features.settings.model.SettingSection;
import org.citra.citra_emu.features.settings.model.Settings;
import org.citra.citra_emu.features.settings.utils.SettingsFile;
import org.citra.citra_emu.utils.EmulationMenuSettings;

/**
 * 快捷菜单栏
 */
public class FloatingLayout extends FrameLayout {
    private ImageView ivBottomScreen, ivScreenLayout;
    private ViewDragHelper mDragHelper;
    private long startCaptureTime;
    private boolean viewCapturing = false;

    private boolean isShowBottomScreen = true;

    public FloatingLayout(@NonNull Context context) {
        this(context, null);
    }

    public FloatingLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FloatingLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        initView();
    }

    private void initView() {
        View.inflate(getContext(), R.layout.view_floating, this);
        ivBottomScreen = findViewById(R.id.iv_bottom_screen);
        ivScreenLayout = findViewById(R.id.iv_screen_layout);
        mDragHelper = ViewDragHelper.create(this, new ViewDragHelper.Callback() {
            //返回true则表示可以捕获该view
            @Override
            public boolean tryCaptureView(@NonNull View view, int i) {
                return true;
            }

            //对child移动的边界进行控制，
            @Override
            public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
                final int leftBound = getPaddingLeft();
                final int rightBound = getWidth() - child.getWidth() - leftBound;
                return Math.min(Math.max(left, leftBound), rightBound);
            }

            @Override
            public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
                final int topBound = getPaddingTop();
                final int bottomBound = getHeight() - child.getHeight() - topBound;
                return Math.min(Math.max(top, topBound), bottomBound);
            }

            @Override
            public void onViewCaptured(@NonNull View capturedChild, int activePointerId) {
                viewCapturing = true;
                startCaptureTime = System.currentTimeMillis();
            }

            @Override
            public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
                viewCapturing = false;
                if (System.currentTimeMillis() - startCaptureTime < 200) {
                    //视为点击事件
                    if (releasedChild == ivBottomScreen) {
                        switchBottomScreen();
                    } else {
                        switchScreenLayout();
                    }
                }
                if (releasedChild == ivBottomScreen) {
                    PrefsHelper.getInstance().setFloatingBottomScreenLocation((int) ivBottomScreen.getX(), (int) ivBottomScreen.getY());
                } else if (releasedChild == ivScreenLayout) {
                    PrefsHelper.getInstance().setFloatingScreenLayoutLocation((int) ivScreenLayout.getX(), (int) ivScreenLayout.getY());
                }
            }
        });
        displayIvBottomScreen();
        displayIvScreenLayout();
    }

    private void switchBottomScreen() {
        isShowBottomScreen = !isShowBottomScreen;
        displayIvBottomScreen();
        NativeLibrary.SwitchBottomScreen(isShowBottomScreen);
    }

    private void displayIvBottomScreen() {
        ivBottomScreen.setImageResource(isShowBottomScreen ? R.drawable.ic_show_bottom_screen : R.drawable.ic_hide_bottom_screen);
    }

    /**
     * 切换屏幕布局
     */
    private void switchScreenLayout() {
        int[] quickScreenLayout = PrefsHelper.getInstance().getQuickScreenLayout();
        if (quickScreenLayout == null) {
            switchScreenLayoutError();
            return;
        }
        //正在使用的屏幕布局
        int currentScreenLayout = PrefsHelper.getInstance().getLastScreenConfigId();
        //如果正在使用的布局是第一个布局，那就切换到第二个布局,否则都切换到第一个布局
        useScreenLayout(currentScreenLayout == quickScreenLayout[0] ? quickScreenLayout[1] : quickScreenLayout[0]);
    }

    /**
     * 使用屏幕布局
     */
    private void useScreenLayout(int id) {
        //是否是内置布局
        boolean isDefaultLayout = id >= EmulationMenuSettings.LayoutOption_Default && id <= EmulationMenuSettings.LayoutOption_MobileLandscape;

        String[] keys = new String[]{SettingsFile.KEY_CUSTOM_LAYOUT,
                SettingsFile.KEY_CUSTOM_TOP_LEFT, SettingsFile.KEY_CUSTOM_TOP_TOP, SettingsFile.KEY_CUSTOM_TOP_RIGHT, SettingsFile.KEY_CUSTOM_TOP_BOTTOM,
                SettingsFile.KEY_CUSTOM_BOTTOM_LEFT, SettingsFile.KEY_CUSTOM_BOTTOM_TOP, SettingsFile.KEY_CUSTOM_BOTTOM_RIGHT, SettingsFile.KEY_CUSTOM_BOTTOM_BOTTOM};
        if (isDefaultLayout) {
            int[] values = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0};
            changeCustomValue(keys, values);
            SwitchScreenLayoutDialog.changeScreenOrientation(id, getWindowRotation());
        } else {
            ScreenConfig config = PrefsHelper.getInstance().getScreenConfig(id);
            if (config == null) {
                //布局被删了或者怎么样
                switchScreenLayoutError();
                return;
            }
            int[] values = new int[]{1, config.getTopLeft(), config.getTopTop(), config.getTopRight(), config.getTopBottom(),
                    config.getBottomLeft(), config.getBottomTop(), config.getBottomRight(), config.getBottomBottom()};
            changeCustomValue(keys, values);
            NativeLibrary.NotifyOrientationChange(EmulationMenuSettings.getLandscapeScreenLayout(), getWindowRotation());
        }
        PrefsHelper.getInstance().setLastScreenConfigId(id);
    }

    private void changeCustomValue(String[] keys, int[] values) {
        Settings mSettings = new Settings();
        mSettings.loadSettings(null);
        for (int i = 0; i < keys.length; i++) {
            String key = keys[i];
            int value = values[i];
            SettingSection rendererSection = mSettings.getSection(Settings.SECTION_LAYOUT);
            Setting customLayout = rendererSection.getSetting(key);
            IntSetting setting = FastSettingDialog.setSelectedValue(value, customLayout, key, Settings.SECTION_LAYOUT);
            if (setting != null) {
                rendererSection.putSetting(setting);
            }
        }
        mSettings.saveSettings(null);
        NativeLibrary.ReloadSettings();
    }

    private int getWindowRotation() {
        if (getContext() instanceof Activity) {
            return ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation();
        }
        WindowManager wm = (WindowManager) App.getContext().getSystemService(Context.WINDOW_SERVICE);
        return wm.getDefaultDisplay().getRotation();
    }

    /**
     * 切换屏幕布局出错
     */
    private void switchScreenLayoutError() {
        PrefsHelper.getInstance().removeQuickScreenLayout();
        displayIvScreenLayout();
    }

    public void displayIvScreenLayout() {
        ivScreenLayout.setVisibility(PrefsHelper.getInstance().isQuickScreenLayout() ? VISIBLE : GONE);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        int[] bottomScreenLocation = PrefsHelper.getInstance().getFloatingBottomScreenLocation();
        if (bottomScreenLocation != null) {
            layoutChild(bottomScreenLocation[0], bottomScreenLocation[1], ivBottomScreen);
        }
        int[] screenLayoutLocation = PrefsHelper.getInstance().getFloatingScreenLayoutLocation();
        if (screenLayoutLocation != null) {
            layoutChild(screenLayoutLocation[0], screenLayoutLocation[1], ivScreenLayout);
        }
    }

    private void layoutChild(int cLeft, int cTop, View view) {
        int cRight = cLeft + view.getMeasuredWidth();
        int cBottom = cTop + view.getMeasuredHeight();
        view.layout(cLeft, cTop, cRight, cBottom);
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return mDragHelper.shouldInterceptTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (viewCapturing) {
            mDragHelper.processTouchEvent(event);
            return true;
        }
        if (isCaptureViewUnder(event.getX(), event.getY())) {
            mDragHelper.processTouchEvent(event);
            return true;
        }
        return false;
    }

    private boolean isViewUnder(View view, float x, float y) {
        if (view == null || view.getVisibility() != VISIBLE) {
            return false;
        }
        return x >= view.getLeft() && x < view.getRight() && y >= view.getTop() && y < view.getBottom();
    }

    private boolean isCaptureViewUnder(float x, float y) {
        return isViewUnder(ivBottomScreen, x, y) || isViewUnder(ivScreenLayout, x, y);
    }

    @Nullable
    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        SavedState ss = new SavedState(superState);
        ss.isShowBottomScreen = isShowBottomScreen ? 1 : 0;
        return ss;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());
        isShowBottomScreen = ss.isShowBottomScreen == 1;
        displayIvBottomScreen();
    }

    private static class SavedState extends BaseSavedState {
        int isShowBottomScreen;

        SavedState(Parcelable superState) {
            super(superState);
        }

        private SavedState(Parcel in) {
            super(in);
            isShowBottomScreen = in.readInt();
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeInt(isShowBottomScreen);
        }

        public static final Parcelable.Creator<SavedState> CREATOR
                = new Parcelable.Creator<SavedState>() {
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }
}
